<?php
/**
 * MineAdmin is committed to providing solutions for quickly building web applications
 * Please view the LICENSE file that was distributed with this source code,
 * For the full copyright and license information.
 * Thank you very much for using MineAdmin.
 *
 * @Author X.Mo<root@imoi.cn>
 * @Link   https://gitee.com/xmo/MineAdmin
 */

declare(strict_types=1);
namespace App\CustHub\Aspect;

use App\Common\Constants\JwtAuthSceneConstants;
use App\Common\Constants\StatusConstants;
use App\CustHub\Annotation\ApiAuth;
use App\CustHub\Mapper\ChUserMapper;
use Hyperf\Di\Annotation\Aspect;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
use Hyperf\Di\Exception\Exception;
use Mine\Exception\TokenException;
use Mine\MineRequest;
use Psr\Container\ContainerInterface;

/**
 * Class AuthAspect
 * @package Mine\Aspect
 */
#[Aspect]
class ApiAuthAspect extends AbstractAspect
{

    public array $annotations = [
        ApiAuth::class
    ];

    /**
     * 容器
     */
    protected ContainerInterface $container;


    public function __construct()
    {
        $this->container = container();
    }

    /**
     * @param ProceedingJoinPoint $proceedingJoinPoint
     * @return mixed
     * @throws Exception
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function process(ProceedingJoinPoint $proceedingJoinPoint)
    {
        $request = $this->container->get(MineRequest::class);


        $scene = JwtAuthSceneConstants::CUST_HUB_URL;
        /** @var $auth ApiAuth */
        if (isset($proceedingJoinPoint->getAnnotationMetadata()->class[ApiAuth::class])) {
            $auth = $proceedingJoinPoint->getAnnotationMetadata()->class[ApiAuth::class];
            $scene = $auth->scene ?? JwtAuthSceneConstants::CUST_HUB_URL;
        }

        if (isset($proceedingJoinPoint->getAnnotationMetadata()->method[ApiAuth::class])) {
            $auth = $proceedingJoinPoint->getAnnotationMetadata()->method[ApiAuth::class];
            $scene = $auth->scene ?? JwtAuthSceneConstants::CUST_HUB_URL;
        }

        //获取代理类 过滤掉不需要登录的方法
        $instance = $proceedingJoinPoint->getInstance();
        if(property_exists($instance,'noNeedLogin')){
            $noNeedLogin = $instance->noNeedLogin;
            $uri = $request->getUri();
            if ($uri->getPath() !== '/favicon.ico' && mb_substr_count($uri->getPath(), '/') > 1) {
                $pathArr = explode('/', $uri->getPath());
                $methodName = end($pathArr);
                if(in_array('*',$noNeedLogin) || in_array($methodName,$noNeedLogin)){
                    return $proceedingJoinPoint->process();
                }
            }
        }

        $uid = $request->input('original_uid');
        if(empty($uid)){
            throw new TokenException(t('system.no_login_user'));
        }

        $loginUser = user($scene);
        if (! $loginUser->check(null, $scene)) {
            throw new TokenException(t('jwt.validate_fail'));
        }

        if($loginUser->getId() != $uid){
            throw new TokenException(t('system.no_login_user'));
        }

        $userInfo = $this->container->get(ChUserMapper::class)->findById($uid);
        if(empty($userInfo) || $userInfo['status'] != StatusConstants::ENABLE ){
            throw new TokenException(t('jwt.validate_fail'));
        }

        return $proceedingJoinPoint->process();
    }
}